package com.settings;

import com.Properties;
import com.dmxrow.MainWindow;
import com.gooddies.exceptions.ErrorMessageException;
import com.gooddies.swing.hComboBox;
import com.gooddies.utils.Base64Coder;
import com.gooddies.utils.FileUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.swingson.Swingson;
import com.swingson.SwingsonGui;
import com.swingson.SwingsonGuiBuilder;
import com.universe.WheelList;
import com.utils.Utils;
import java.awt.HeadlessException;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JTextPane;

/**
 * @author sad
 */
public class SettingsDialog extends JFrame {

    private final hComboBox<Profile> profileCombo = new hComboBox<>();
    private final JTextField profileTF = new JTextField();
    private final JTextField portTF = new JTextField();
    private final JTextField rowTF = new JTextField();
    private final JCheckBox continiousUniverseCB = new JCheckBox();
    private final JTextPane wheelsPane = new JTextPane();

    public SettingsDialog() throws HeadlessException {
        setTitle("DmxReceiver statup");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        SwingsonGui gui = SwingsonGuiBuilder.createGuiFromJsonInPackage(this);
        loadProfiles();
        if (profileCombo.getSelectedItem() != null) {
            showProfile(profileCombo.getSelectedItem());
        }
    }

    private void onProfileSelected() {
        Profile profile = profileCombo.getSelectedItem();
        showProfile(profile);
    }

    private void showProfile(Profile profile) {
        profileTF.setText(profile.getName());
        portTF.setText("" + profile.getPort());
        rowTF.setText("" + profile.getRow());
        continiousUniverseCB.setSelected(profile.isContinious());
        wheelsPane.setText(new GsonBuilder().setPrettyPrinting().create().toJson(profile.getWheels()));
    }

    private void loadProfiles() {
        try (Swingson.UserInputEnabler en = Swingson.disableUserInput()) {
            profileCombo.clearItems();
            File profs = new File("./profiles.txt");
            if (!profs.exists()) {
                return;
            }
            String content = FileUtils.readToString(profs, "UTF-8");
            if (content.trim().isEmpty()) {
                return;
            }
            String[] strs = content.split("\\r?\\n");
            for (String s : strs) {
                s = s.trim();
                if (s.isEmpty()) {
                    continue;
                }

                String[] parsed = s.split("→");
                if (parsed.length == 4) {
                    Profile prof = new Profile();
                    prof.setName(parsed[0]);
                    prof.setPort(Integer.parseInt(parsed[1]));
                    prof.setRow(Integer.parseInt(parsed[2]));
                    prof.setContinious(Boolean.parseBoolean(parsed[3]));
                    profileCombo.addItem(prof);
                }
                if (parsed.length == 5) {
                    Profile prof = new Profile();
                    prof.setName(parsed[0]);
                    prof.setPort(Integer.parseInt(parsed[1]));
                    prof.setRow(Integer.parseInt(parsed[2]));
                    prof.setContinious(Boolean.parseBoolean(parsed[3]));
                    try {
                        String wheels = new String(Base64Coder.decode(parsed[4]), "UTF-8");
                        WheelList wheelsList = getWheelFromJson(wheels);
                        prof.setWheels(wheelsList);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    profileCombo.addItem(prof);
                }
            }
        }
    }

    private boolean validateWheelJson() {
        try {
            String value = wheelsPane.getText();
            value = value.trim();
            WheelList wheelList = new Gson().fromJson(value, WheelList.class);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    private WheelList getWheelFromJson(String value) {
        try {
            value = value.trim();
            WheelList wheelList = new Gson().fromJson(value, WheelList.class);
            return wheelList;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        throw new ErrorMessageException("Wheel json is not valid");
    }

    private void onPopupMenuGenerateExampleSelected() {
        String value = "{\n"
                + "  \"wheels\":[\n"
                + "     {\n"
                + "        \"universeIndex\":2,\n"
                + "        \"channel\":509\n,"
                + "        \"x\":7\n,"
                + "        \"y\":7\n,"
                + "     }\n"
                + "   ]\n"
                + "}";
        wheelsPane.setText(value);
    }

    public void onStart() throws Exception {
        if (profileTF.getText().isEmpty()) {
            Utils.showError("Please select profile");
            return;
        }
        if (portTF.getText().isEmpty()) {
            Utils.showError("Please enter port");
            return;
        }
        if (rowTF.getText().isEmpty()) {
            Utils.showError("Please enter row");
            return;
        }
        if (!validateWheelJson()) {
            Utils.showError("Please enter valid JSON in field 'wheels'");
            return;
        }

        String profileName = profileTF.getText();
        int port = Integer.parseInt(portTF.getText());
        int row = Integer.parseInt(rowTF.getText());
        Profile profile = new Profile();
        profile.setName(profileName);
        profile.setPort(port);
        profile.setRow(row);
        profile.setContinious(continiousUniverseCB.isSelected());
        profile.setWheels(getWheelFromJson(wheelsPane.getText()));
        saveProfile(profile);
        Properties.profile = profile;
        setVisible(false);
        dispose();
        MainWindow window = new MainWindow();
        window.pack();
        window.setLocationRelativeTo(null);
        window.setVisible(true);
    }

    private void saveProfile(Profile prof) {
        try (Swingson.UserInputEnabler en = Swingson.disableUserInput()) {
            loadProfiles();
            boolean found = false;
            for (int i = 0; i < profileCombo.getItemCount(); i++) {
                Profile p = profileCombo.getItemAt(i);
                if (p.getName().equals(prof.getName())) {
                    p.setName(prof.getName());
                    p.setPort(prof.getPort());
                    p.setRow(prof.getRow());
                    p.setContinious(prof.isContinious());
                    p.setWheels(prof.getWheels());
                    found = true;
                    break;
                }
            }

            if (found == false) {
                profileCombo.addItem(prof);
            }

            File profs = new File("./profiles.txt");
            try {
                try (PrintStream stream = new PrintStream(profs,"UTF-8")) {
                    for (int i = 0; i < profileCombo.getItemCount(); i++) {
                        Profile p = profileCombo.getItemAt(i);
                        stream.println(p.formatString());
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

}
